home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
general
/
viewers
/
polyview
/
polyvw31.lha
/
Polyview3.1
/
new
/
pvinfo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-24
|
21KB
|
674 lines
/*****************************************************************************
* NCSA Polyview 3.1 *
* *
* Version 3.1 changes and additions by Gilles Bourhis. *
* Version 3 changes and additions by Marc Andreessen. *
* Version 2 by Brian Calvert. *
* *
* Software Development Group *
* National Center for Supercomputing Applications *
* University of Illinois at Urbana-Champaign *
* *
* This is BETA release software. As such it may contain software bugs and *
* exhibit inconsistencies. *
* *
* Please send bug reports to polyview@ncsa.uiuc.edu. *
* *
* Copyright (c) 1992 The Board of Trustees of the University of Illinois. *
* *
* Permission to use, copy, and modify this software and its *
* documentation for educational, research, and non-profit purposes is *
* hereby granted, provided that the above copyright notice, the original *
* authors names, and this permission notice appear in all such copies. *
* Any distribution of this software requires the explicit and written *
* authorization of the authors. *
* *
* The University of Illinois makes no representations about the *
* suitability of this software for any purpose. It is provided "as is" *
* without warranty of any kind. *
*****************************************************************************/
/* $Id: pvinfo.c,v 1.2 93/08/24 10:29:53 gbourhis Exp $ */
#ifdef RCSLOG
$Log: pvinfo.c,v $
* Revision 1.2 93/08/24 10:29:53 gbourhis
* replace version string 3.0 by 3.1
*
* Revision 1.1 92/09/18 10:55:26 marca
* Initial revision
*
#endif
#include "pv.h"
static window_t *info_win = NULL;
static Widget info_base = NULL;
static Widget info_text = NULL;
static int info_is_posted = 0;
/* Number of items in our dialog box. */
static int numitems;
static int itemval = 1;
/* ------------------------------------------------------------------------ */
static int local_reset(state_t *state, window_t *win, void *w)
{
return parse_line (state, "information reset", TRUE);
}
/* ------------------------------------------------------------------------ */
/* ------------------------- ConstructInfoString -------------------------- */
/* ------------------------------------------------------------------------ */
#define STRCHUNK 100000
#define ARBITRARY_LIMIT 300
static int current_size = 0;
static char *str = NULL;
static void local_strprintf(char * format, ...)
{
va_list args;
char line[MAXLINELEN];
va_start(args, format);
/* Put string in line. */
vsprintf(line, format, args);
/* Get more space if we think we need it. */
if (current_size - strlen(str) < 80)
{
current_size += STRCHUNK;
str = (char *)realloc (str, current_size * sizeof(char));
bzero (&(str[current_size - STRCHUNK]), STRCHUNK);
}
/* Put line in info string. */
strcat (str, line);
strcat (str, "\n\0");
va_end(args);
return;
}
static int ConstructInfoString (state_t *state, window_t *win)
{
window_t *active;
object_t *obj;
float *pcoord;
long k;
pickmode_t pickmode;
float scalar;
/* Fetch the active window. */
active = win;
/* Get the first item in the window. */
itemval = 1;
if ((active != NULL) && WinHasData(active))
{
/* Get the object and the element within it. */
obj = GetKthElementObj(WIN_CURROOTOBJ(active), itemval);
k = GetKthPickedElement(obj, itemval);
/* Set the pickmode according to whatever was found. */
if ((obj == NULL) || (k == -1))
{
/* If nothing is currently selected, set the pickmode */
/* as if everything were selected. */
pickmode = PICK_ALL;
itemval = 1;
numitems = 1;
}
else
{
pickmode = OBJ_PICKMODE(obj);
}
}
else
{
/* Clear out the window. */
XmxTextSetString (info_text, "No information.");
}
/* Start up the string; we'll realloc in local_strprintf if
we need to. */
str = (char *)malloc (STRCHUNK * sizeof(char));
bzero (str, STRCHUNK);
current_size = STRCHUNK;
/* Now actually fill in the panel with information according to */
/* the state of the system. */
if (active == NULL)
{
/* No active window. */
local_strprintf
("Active Window\n %-6s %s\n %-6s %s\n %-6s %s\n %-6s %s\n %-6s %s\n %-6s %s\n %-6s %s\n", "Name", "<none>",
"File", "<none>",
"Frame", "<none>",
"X", "<none>",
"Y", "<none>",
"Z", "<none>",
"Color", "<none>");
}
else if (WinHasNoData(active))
{
/* Active window contains no data. */
local_strprintf( "Active Window (no data)");
local_strprintf( " %-6s %s", "Name",
WIN_NAME(active));
local_strprintf( " %-6s %s", "File",
WIN_SOURCENAME(active));
local_strprintf( " %-6s %s", "Frame",
WIN_GROUPNAME(active));
local_strprintf( " %-6s %s", "X",
WIN_PXNAME(active));
local_strprintf( " %-6s %s", "Y",
WIN_PYNAME(active));
local_strprintf( " %-6s %s", "Z",
WIN_PZNAME(active));
local_strprintf( " %-6s %s", "Color",
WIN_VSCALARNAME(active));
}
else
{
switch (pickmode)
{
case PICK_VERTEX:
for (itemval = 1; itemval <= numitems; itemval++)
{
/* Get the object and the element within it. */
obj = GetKthElementObj(WIN_CURROOTOBJ(active), itemval);
k = GetKthPickedElement(obj, itemval);
scalar = GetVertexScalar(state, obj, k);
pcoord = GetVertexCoord(state, obj, k);
local_strprintf
( "Vertex %ld of %ld\n %-6s %s\n %-6s %-9s %.3e\n %-6s (%.3f %.3f %.3f)",
itemval, WIN_SELECTED(active), "Name",
OBJ_NAME(obj),
"Scalar", GetVdataName(obj, MVSCALAR), scalar,
"Coord", pcoord[X], pcoord[Y], pcoord[Z]);
if (itemval >= ARBITRARY_LIMIT)
{
local_strprintf("**** Exceeded reasonableness limit.\n**** Remaining primitives not reported.");
goto done_vertices;
}
}
done_vertices:
break;
case PICK_FACE:
for (itemval = 1; itemval <= numitems; itemval++)
{
/* Get the object and the element within it. */
obj = GetKthElementObj(WIN_CURROOTOBJ(active), itemval);
k = GetKthPickedElement(obj, itemval);
scalar = GetFaceScalar(state, obj, k);
pcoord = GetFaceCoord(state, obj, k);
local_strprintf
( "Face %ld of %ld\n %-6s %s\n %-6s %-9s %.3e\n %-6s (%.3f %.3f %.3f)",
itemval, WIN_SELECTED(active),
"Name",
OBJ_NAME(obj),
"Scalar", GetVdataName(obj, MVSCALAR), scalar,
"Coord", pcoord[X], pcoord[Y], pcoord[Z]);
if (itemval >= ARBITRARY_LIMIT)
{
local_strprintf("**** Exceeded reasonableness limit.\n**** Remaining primitives not reported.");
goto done_faces;
}
}
done_faces:
break;
case PICK_OBJECT:
for (itemval = 1; itemval <= numitems; itemval++)
{
/* Get the object and the element within it. */
obj = GetKthElementObj(WIN_CURROOTOBJ(active), itemval);
k = GetKthPickedElement(obj, itemval);
local_strprintf
( "Object %ld of %ld\n %-6s %s\n %-6s %ld\n %-6s %ld\n %-6s (%.3f %.3f %.3f)\n %-6s (%.3f %.3f %.3f)\n %-6s (%.3f %.3f %.3f)",
itemval, WIN_SELECTED(active),
"Name",
OBJ_NAME(obj),
"Verts",
OBJ_STATS(obj,PX,0).rec_count,
"Polys",
OBJ_STATS(obj,MCONNECT,0).rec_count,
"Min", OBJ_STATS(obj,PX,0).min,
OBJ_STATS(obj,PY,0).min,
OBJ_STATS(obj,PZ,0).min,
"Mean", OBJ_STATS(obj,PX,0).mean,
OBJ_STATS(obj,PY,0).mean,
OBJ_STATS(obj,PZ,0).mean,
"Max", OBJ_STATS(obj,PX,0).max,
OBJ_STATS(obj,PY,0).max,
OBJ_STATS(obj,PZ,0).max);
if (itemval >= ARBITRARY_LIMIT)
{
local_strprintf("**** Exceeded reasonableness limit.\n**** Remaining primitives not reported.");
goto done_objects;
}
}
done_objects:
break;
case PICK_NONE:
case PICK_ALL:
local_strprintf( "Active Window");
local_strprintf( " %-6s %s", "Name",
WIN_NAME(active));
local_strprintf( " %-6s %s", "File",
WIN_SOURCENAME(active));
local_strprintf( " %-6s %s", "Frame",
WIN_GROUPNAME(active));
local_strprintf( " %-6s %s", "X",
WIN_PXNAME(active));
local_strprintf( " %-6s %s", "Y",
WIN_PYNAME(active));
local_strprintf( " %-6s %s", "Z",
WIN_PZNAME(active));
local_strprintf( " %-6s %s", "Color",
WIN_VSCALARNAME(active));
break;
default:
local_strprintf( "<ERROR>");
break;
}
}
XmxTextSetString (info_text, str);
free (str);
str = NULL;
return ST_OKAY;
}
/* ------------------------------------------------------------------------ */
int init_info_fn(state_t *state, window_t *win, int reset)
{
return init_info (state, state->active_windows, win, reset);
}
/* ------------------------------------------------------------------------ */
/* palette and reset aren't used here, but what the hell. */
int init_info(state_t *state, window_t *active, window_t *palette, int reset)
{
if ((active == NULL) || (WIN_FRAMELIST(active) == NULL))
{
/* No active window or frame. Empty the window. */
XmxTextSetString (info_text, "No information.");
numitems = 1;
}
else
{
if ((WIN_CURROOTOBJ(active) != NULL) &&
(WIN_ROOTOBJINFO(active) != NULL))
{
/* Set the number of items in the goddamn text. */
numitems = WIN_SELECTED(active);
}
}
if (active == palette)
active = state->active_windows;
ConstructInfoString (state, active);
return ST_OKAY;
}
/* ------------------------------------------------------------------------ */
char *GetVdataName(object_t *obj, int slot)
{
Vdata_t *vdata;
char *name;
/* Get a pointer to the vdata, if any. */
if (obj == NULL)
vdata = NULL;
else
vdata = OBJ_VDATA(obj, slot);
if ((vdata == NULL) || (*VDA_NAME(vdata) == '\0'))
name = "<none>";
else
name = VDA_NAME(vdata);
return name;
}
/* ------------------------------------------------------------------------ */
long GetKthPickedElement(object_t *obj, long k)
{
long i;
char *picked;
/* If the object is NULL, return a nonsense value. */
if (obj == NULL)
return -1;
/* Find out how many picked elements to skip in the picked list. */
k -= OBJ_FIRSTID(obj);
picked = OBJ_PICKLIST(obj);
if (picked == NULL)
return -1;
assert (k >= 0);
/* Search for the kth selected element. */
for (i = 0; k >= 0; i++, picked++)
if (*picked)
{
k--;
if (k < 0)
break;
}
/* Return the index of the element. */
return i;
}
/* ------------------------------------------------------------------------ */
float GetVertexScalar(state_t *state, object_t *obj, long k)
{
float *scalar;
/* Get a pointer to the object's vdata list. */
if ((scalar = (float *) get_data(state, OBJ_VDATA(obj, MVSCALAR))) ==
NULL)
return 0.0;
else
return scalar[k];
}
/* ------------------------------------------------------------------------ */
float *GetVertexCoord(state_t *state, object_t *obj, long k)
{
float *pcoord;
/* Get a pointer to the object's vdata list. */
if ((pcoord = (float *) get_data(state, OBJ_VDATA(obj, PCOORD))) == NULL)
return NULL;
else
return pcoord + DIMS*k;
}
/* ------------------------------------------------------------------------ */
int GetVertexColor(state_t *state, object_t *obj, long k)
{
int *colorp;
/* Get a pointer to the object's vdata list. */
if ((colorp = (int *) get_data(state, OBJ_VDATA(obj, VCOLOR))) == NULL)
return 0;
else
return colorp[k];
}
/* ------------------------------------------------------------------------ */
float GetFaceScalar(state_t *state, object_t *obj, long k)
{
long *connect;
float *scalar;
long nvert;
float value;
long i, j;
/* Get a pointer to the object's connectivity list. */
if (((connect = (long *) get_data(state, OBJ_VDATA(obj, MCONNECT)))
== NULL) ||
((scalar = (float *) get_data(state, OBJ_VDATA(obj, MVSCALAR)))
== NULL))
return 0.0;
else
{
/* Adjust the connect list pointer to point to the first */
/* vertex of the selected polygon. */
value = 0.0;
connect += k * OBJ_STATS(obj, MCONNECT, 0).rec_size;
for (i = VDA_STATS(OBJ_VDATA(obj, MCONNECT)).rec_size, j = 0;
i > 0; i--, j++, connect++)
{
if (*connect == 0)
break;
else
value += scalar[*connect - 1];
}
return value / j;
}
}
/* ------------------------------------------------------------------------ */
float *GetFaceCoord(state_t *state, object_t *obj, long k)
{
long *connect;
float *pcoord;
static float center[DIMS];
long nvert;
long i, j;
/* Get a pointer to the object's connectivity list. */
if (((connect =
(long *) get_data(state, OBJ_VDATA(obj, MCONNECT))) == NULL) ||
((pcoord = (float *) get_data(state, OBJ_VDATA(obj, PCOORD))) == NULL))
{
return NULL;
}
else
{
/* Adjust the connect list pointer to point to the first */
/* vertex of the selected polygon. */
center[X] = center[Y] = center[Z] = 0.0;
connect += k * OBJ_STATS(obj, MCONNECT, 0).rec_size;
for (i = VDA_STATS(OBJ_VDATA(obj, MCONNECT)).rec_size, j = 0;
i > 0; i--, j++, connect++)
{
if (*connect == 0)
break;
else
{
center[X] += pcoord[X + DIMS*(*connect - 1)];
center[Y] += pcoord[Y + DIMS*(*connect - 1)];
center[Z] += pcoord[Z + DIMS*(*connect - 1)];
}
}
/* Average the coordinates. */
center[X] /= j;
center[Y] /= j;
center[Z] /= j;
return center;
}
}
/* ------------------------------------------------------------------------ */
/* Returns a pointer to the object containing the kth selected element in */
/* the sub-tree defined by "root". Returns NULL if no such node. */
object_t *GetKthElementObj(object_t *root, int k)
{
object_t *prev, *curr;
/* If k == 0, there are no objects selected. Quit. */
if (k == 0)
return NULL;
/* If the root is an atomic object, assume k is contained in it. */
if (OBJ_TYPE(root) == ATOM)
return root;
/* Keep a pointer to the last node examined, in case we pass it. */
/* Keep passing siblings until we either find the proper object */
/* or run out of objects. */
for (prev = NULL, curr = OBJ_CHILD(root); curr;
prev = curr, curr = OBJ_SIBLING(curr))
{
if (k < OBJ_FIRSTID(curr))
break;
}
/* prev points to the object of interest. If it is a composite, */
/* search its children. Otherwise, return it. */
if (OBJ_TYPE(prev) == OBJECT)
return GetKthElementObj(prev, k);
else
return prev;
}
/* ------------------------------------------------------------------------ */
static XmxCallback (GUIinfoButtonCB)
{
switch (XmxExtractToken ((int)client_data))
{
case PV_INFO_BUTTON_OK:
parse_line (gstate, "window close information", TRUE);
break;
case PV_INFO_BUTTON_HELP:
GUIdoHelp (PV_INFO_BUTTON_HELP);
break;
}
return;
}
void destroy_info (state_t *state, window_t *window)
{
XtUnmanageChild (info_base);
info_is_posted = 0;
return;
}
void create_info_dialog(state_t *state)
{
Widget dialog_frame;
Widget info_form, buttons_form;
Widget dialog_sep;
/* Create if necessary; definitely pop up. */
if (info_base == NULL)
{
XmxSetUniqid (0);
/* Create a new info window. */
info_base = XmxMakeFormDialog (state->base, "Polyview 3.1: Info Window");
/* We put a frame inside the dialog form, then put a form
inside that. */
dialog_frame = XmxMakeFrame (info_base, XmxShadowOut);
/* Constraints for base. */
XmxSetConstraints
(dialog_frame, XmATTACH_FORM, XmATTACH_FORM,
XmATTACH_FORM, XmATTACH_FORM,
NULL, NULL, NULL, NULL);
/* Main form. */
info_form = XmxMakeForm (dialog_frame);
/* Info window: text widget, not editable. */
XmxSetArg (XmNscrolledWindowMarginWidth, 10);
XmxSetArg (XmNscrolledWindowMarginHeight, 10);
XmxSetArg (XmNcursorPositionVisible, False);
XmxSetArg (XmNeditable, False);
XmxSetArg (XmNeditMode, XmMULTI_LINE_EDIT);
XmxSetArg (XmNrows, 15);
XmxSetArg (XmNcolumns, 50);
info_text = XmxMakeScrolledText (info_form);
/* Load up initial text, by hand; don't use GUIsetInfo. */
/* XmxTextSetString (info_text, txt); */
dialog_sep = XmxMakeHorizontalSeparator (info_form);
buttons_form = XmxMakeFormAndTwoButtons
(info_form, GUIinfoButtonCB, "OK", "Help", PV_INFO_BUTTON_OK,
PV_INFO_BUTTON_HELP);
/* Constraints for info_form. */
/* XmxSetOffsets (XtParent (info_text), 10, 10, 10, 10); */
XmxSetConstraints
(XtParent (info_text), XmATTACH_FORM, XmATTACH_WIDGET,
XmATTACH_FORM, XmATTACH_FORM, NULL, dialog_sep, NULL, NULL);
XmxSetArg (XmNtopOffset, 10);
XmxSetConstraints
(dialog_sep, XmATTACH_NONE, XmATTACH_WIDGET, XmATTACH_FORM,
XmATTACH_FORM,
NULL, buttons_form, NULL, NULL);
XmxSetConstraints
(buttons_form, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM,
XmATTACH_FORM,
NULL, NULL, NULL, NULL);
/* Add the window to the internal structs so we get messages. */
info_win = add_window (state, "info", DIALOG,
NULL /* init */,
NULL /* redraw */,
NULL /* animate */,
NULL /* event */,
notify_info /* notify */,
NULL /* destroy */);
}
/* Manage or remanage. */
XmxManageRemanage (info_base);
info_is_posted = 1;
/* We do this instead of registering init_info as init function
in add_window above, because this works, and that doesn't. */
init_info_fn (state, info_win, 1);
return;
}
int notify_info(state_t * state, window_t * send_win, window_t * recv_win,
int message, va_list args)
{
int status;
window_t *active;
status = ST_OKAY;
if (info_is_posted)
{
active = state->active_windows;
switch (message)
{
case MSG_NEWACT: /* new active window only */
init_info(state, send_win, recv_win, TRUE);
break;
case MSG_NEWPICK:
case MSG_NEWFRAME:
case MSG_NEWDATA:
/* Only update the window if this is the current window. */
if (send_win == state->active_windows)
init_info(state, send_win, recv_win, FALSE);
break;
case MSG_CLOSING:
case MSG_VIEWCHG:
case MSG_REDRAW:
default:
break;
}
}
return status;
}